/**
 * $Revision$
 * $Date$
 *
 * Copyright (C) https://gitee.com/baibaiclouds/platform loon. All rights reserved.
 * <p>
 * This software is the confidential and proprietary information of loon.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the agreements you entered into with loon.
 * 
 * Modified history:
 *   Loon  2019年11月3日 下午10:05:36  created
 */
package com.desktop.web.service.user;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.desktop.web.core.comenum.Status;
import com.desktop.web.core.exception.BusinessException;
import com.desktop.web.core.utils.Util;
import com.desktop.web.service.config.ConfigService;
import com.desktop.web.service.device.DeviceService;
import com.desktop.web.service.log.LogService;
import com.desktop.web.service.role.RoleService;
import com.desktop.web.service.session.Client;
import com.desktop.web.uda.entity.DeviceSettings;
import com.desktop.web.uda.entity.Role;
import com.desktop.web.uda.entity.RoleUser;
import com.desktop.web.uda.entity.User;
import com.desktop.web.uda.mapper.RoleMapper;
import com.desktop.web.uda.mapper.RoleUserMapper;
import com.desktop.web.uda.mapper.UserMapper;

/**
 * 
 *
 * @author baibai
 */
@Service
public class UserService implements InitializingBean {

    public static final int USERNAME_MIN_LEN = 6;
    public static final Long ADMIN_ROLE_ID = 0L;
    public static final Long DEFAULT_ROLE_ID = -1L;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${user.reset.password.timeout}")
    private Integer RESET_PASSWORD_TIMEOUT;

    @Value("${spring.mail.username}")
    private String SPRING_MAIL_USERNAME;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private LogService logService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private RoleService roleService;

    private Map<Long, User> uidToUser = new HashMap<Long, User>();
    private Map<String, Long> usernameToUid = new HashMap<String, Long>();

    @Override
    public void afterPropertiesSet() throws Exception {

    }

    /**
     * 根据登录名称获取用户详细信息
     * 
     * @param username
     * @return
     */
    public User getUserByUsername(String username) {
        Long uid = usernameToUid.get(username);
        if (uid != null) {
            return uidToUser.get(uid);
        }

        User user = new User();
        user.setUsername(username);
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        queryWrapper.setEntity(user);
        user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            return null;
        }

        this.addUserCache(user);
        return user;
    }

    /**
     * 根据id获取用户信息
     * 
     * @param uid
     * @return
     */
    public User getUserById(Long uid) {
        User user = uidToUser.get(uid);
        if (user != null) {
            return user;
        }

        user = userMapper.selectById(uid);
        if (user == null) {
            return null;
        }

        addUserCache(user);
        return user;
    }

    /**
     * 添加用户信息到缓存
     * 
     * @param uesr
     */
    private void addUserCache(User uesr) {
        uidToUser.put(uesr.getId(), uesr);
        usernameToUid.put(uesr.getUsername(), uesr.getId());
    }

    /**
     * 获取用户配置信息
     * 
     * @param user
     * @param sn
     * @return
     */
    public Object getSettings(Client client) {

        DeviceSettings settings = deviceService.getDeviceSettings(client.getSn());

        Map<String, Object> ret = new HashMap<>();
        ret.put("autoRemote", settings.getAutoRemote());
        ret.put("autoRun", settings.getAutoRun());
        return ret;
    }

    /**
     * 更新用户配置
     * 
     * @param user
     * @param sn
     * @param params
     * @return
     */
    public Object updateSettings(Client client, Map<String, String> params) {
        DeviceSettings deviceSettings = new DeviceSettings();
        deviceSettings.setAutoRemote(Status.valueOf(params.get("autoRemote")));
        deviceSettings.setAutoRun(Status.valueOf(params.get("autoRun")));
        deviceService.updateDeviceSettings(client.getSn(), deviceSettings);
        return null;
    }

    /**
     * 根据用户id列表获取用户
     * 
     * @param uids
     * @return
     */
    public List<User> getUserListByIds(List<Long> uids) {
        List<User> users = userMapper.selectBatchIds(uids);
        users.forEach((item) -> {
            item.setPassword(null);
        });

        return users;
    }

    /**
     * 添加用户
     * 
     * @param user
     * @return
     */
    public User addUser(User user) {

        User tempuser = this.getUserByUsername(user.getUsername());
        if (tempuser != null) {
            throw new BusinessException(user.getUsername() + " 登录名称已存在");
        }

        user.setCtime(new Date());
        userMapper.insert(user);
        logger.info("add user success,username:{},selfname:{}", user.getUsername(), user.getSelfname());
        return user;
    }

    /**
     * 把用户添加到具体角色上
     * 
     * @param roleId
     * @param user
     */
    public void addUserRole(Long roleId, User user) {
        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(user.getId());
        roleUserMapper.insert(roleUser);
    }

    /**
     * 添加用户
     * 
     * @param username
     * @param selfname
     * @param password
     * @return
     */
    public User addUser(String username, String selfname, String password) {
        User user = new User();
        user.setSelfname(selfname);
        user.setUsername(username);
        user.setPassword(password);

        return this.addUser(user);
    }

    /**
     * 根据用户组id获取用户列表
     * 
     * @param roleId
     * @return
     */
    public List<User> getUserListByRoleid(Long roleId) {

        RoleUser entity = new RoleUser();
        entity.setRoleId(roleId);
        QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<RoleUser>();
        queryWrapper.setEntity(entity);
        queryWrapper.orderByDesc("id");
        List<RoleUser> roleUsers = roleUserMapper.selectList(queryWrapper);
        List<Long> uids = new ArrayList<Long>();
        for (RoleUser item : roleUsers) {
            uids.add(item.getId());
        }

        if (uids.isEmpty()) {
            return new ArrayList<User>();
        }

        QueryWrapper<User> queryWrapperUser = new QueryWrapper<User>();
        userMapper.selectList(queryWrapperUser);
        return userMapper.selectBatchIds(uids);
    }

    /**
     * 用户用户列表
     * 
     * @return
     */
    public List<User> getUserList(String username, String selfname) {
        QueryWrapper<User> queryWrapperUser = new QueryWrapper<User>();
        queryWrapperUser.orderByDesc("id");

        if (!StringUtils.isEmpty(username)) {
            queryWrapperUser.like("username", username);
        }

        if (!StringUtils.isEmpty(selfname)) {
            queryWrapperUser.like("selfname", selfname);
        }

        List<User> users = userMapper.selectList(queryWrapperUser);
        users.forEach((user) -> {
            user.setPassword(null);
            user.setRoleName(this.getRoleNamesByUid(user.getId()));
        });
        return users;
    }

    /**
     * 根据用户id获取角色名称列表
     * 
     * @param uid
     * @return
     */
    public String getRoleNamesByUid(Long uid) {
        RoleUser entity = new RoleUser();
        entity.setUserId(uid);
        QueryWrapper<RoleUser> queryWrapperUser = new QueryWrapper<RoleUser>();
        queryWrapperUser.setEntity(entity);
        List<RoleUser> roleUserList = roleUserMapper.selectList(queryWrapperUser);

        if (roleUserList.isEmpty()) {
            return "";
        }

        List<Long> ids = new ArrayList<Long>();
        for (RoleUser item : roleUserList) {
            ids.add(item.getRoleId());
        }

        List<Role> roleList = roleMapper.selectBatchIds(ids);
        if (roleList.isEmpty()) {
            return "";
        }

        StringBuffer sb = new StringBuffer();
        roleList.forEach((item) -> {
            if (sb.length() == 0) {
                sb.append(item.getTitle());
            } else {
                sb.append("," + item.getTitle());
            }
        });

        return sb.toString();
    }

    /**
     * 更新用户信息
     * 
     * @param user
     */
    public void updateUser(User user) {

        Long rootuid = configService.getAdminRootUID();
        if (rootuid.equals(user.getId())) {
            throw new BusinessException("默认的超级管理员信息只能自己修改");
        }

        cleanUserCache(user.getId());
        userMapper.updateById(user);
        logService.addLogCuruser("用户管理", "更新了用户信息", "");
    }

    /**
     * 清空用户缓存信息
     * 
     * @param uid
     */
    private void cleanUserCache(Long uid) {
        User user = this.uidToUser.get(uid);
        if (user == null) {
            return;
        }

        this.uidToUser.remove(uid);
        this.usernameToUid.remove(user.getUsername());
    }

    /**
     * 删除用户
     * 
     * @param uid
     */
    public void deleteUser(Long uid) {
        Long rootuid = configService.getAdminRootUID();
        if (rootuid.equals(uid)) {
            throw new BusinessException("默认的超级管理员无法删除");
        }

        User user = this.getUserById(uid);
        if (user == null) {
            throw new BusinessException("参数非法");
        }

        roleService.deleteRoleUser(uid);

        this.cleanUserCache(uid);
        userMapper.deleteById(uid);
        this.logService.addLogCuruser("用户管理", "删除用户，用户登录名称:{}", user.getUsername());
    }

    /**
     * 获取用户总数量
     * 
     * @return
     */
    public int getUserCount() {
        return userMapper.selectCount(null);
    }

    /**
     * 获取用户基本信息
     * 
     * @param uid
     * @return
     */
    public Object getUserInfo(Long uid) {
        User user = this.getUserById(uid);

        List<String> roleNames = new ArrayList<String>();
        List<Role> roles = roleService.getRoleListByUid(uid);
        for (Role item : roles) {
            roleNames.add(item.getTitle());
        }

        Map<String, Object> userinfo = new HashMap<String, Object>();
        userinfo.put("username", user.getUsername());
        userinfo.put("selfname", user.getSelfname());
        userinfo.put("roles", Util.listToString(roleNames));
        return userinfo;
    }

    /**
     * 修改用户密码
     * 
     * @param uid
     * @param oldpw
     * @param newpw
     */
    public void updateSelfpw(Long uid, String oldpw, String newpw) {
        if (StringUtils.isEmpty(oldpw) || StringUtils.isEmpty(newpw)) {
            throw new BusinessException("参数错误");
        }

        User user = this.getUserById(uid);
        if (!user.getPassword().equals(oldpw)) {
            throw new BusinessException("旧密码错误");
        }

        User update = new User();
        update.setId(uid);
        update.setPassword(newpw);
        userMapper.updateById(update);
        this.cleanUserCache(uid);

        this.logService.addLogCuruser("用户管理", "修改密码成功，用户登录名称:{}", user.getUsername());
    }

}
